<!doctype html><html lang=en-us dir=ltr><head><meta charset=UTF-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content="Sqlalchemy异步操作不完全指北 - 米洛丶 - 博客园 # cnblogs.com
异步SQLAlchemy # SQLAlchemy作为一款通用的Python Orm工具，在最近的版本也支持了异步操作。但网上很多资料都不是很齐全，API也不是很好查询的情况下，我便有了整理一份基础文档的想法。文章主要会以CRUD为入口，解决大家最基本的需求。
engine的区别 # 在普通的SQLAlchemy中，建立engine对象，我们会采用下面的方式:
from sqlalchemy import create_engine engine = create_engine(SQLALCHEMY_DATABASE_URI, pool_recycle=1500) 而异步的方式如下:
from sqlalchemy.ext.asyncio import create_async_engine async_engine = create_async_engine(ASYNC_SQLALCHEMY_URI, pool_recycle=1500) session的区别 # 我们一般用sessionmaker来建立session，不过异步的有点区别:
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import sessionmaker # 同步session Session = sessionmaker(engine) # 异步session 区别在于需要指定对应的class_ async_session = sessionmaker(async_engine, class_=AsyncSession) 建立会话 # 我们还是以代码的形式展示:
# 同步 with Session() as session: # 里面是具体的sql操作 pass # 异步 async with Session() as session: # 里面是异步的操作，区别就是从with变成了async with 也就意味着方法必须是async修饰的 pass 以上是关于建立连接，处理会话的一些区别，接着我们讲对应的CRUD操作。"><meta name=theme-color content="#FFFFFF"><meta name=color-scheme content="light dark"><meta property="og:title" content="SqlAlchemy - 数据库Orm"><meta property="og:description" content="Sqlalchemy异步操作不完全指北 - 米洛丶 - 博客园 # cnblogs.com
异步SQLAlchemy # SQLAlchemy作为一款通用的Python Orm工具，在最近的版本也支持了异步操作。但网上很多资料都不是很齐全，API也不是很好查询的情况下，我便有了整理一份基础文档的想法。文章主要会以CRUD为入口，解决大家最基本的需求。
engine的区别 # 在普通的SQLAlchemy中，建立engine对象，我们会采用下面的方式:
from sqlalchemy import create_engine engine = create_engine(SQLALCHEMY_DATABASE_URI, pool_recycle=1500) 而异步的方式如下:
from sqlalchemy.ext.asyncio import create_async_engine async_engine = create_async_engine(ASYNC_SQLALCHEMY_URI, pool_recycle=1500) session的区别 # 我们一般用sessionmaker来建立session，不过异步的有点区别:
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import sessionmaker # 同步session Session = sessionmaker(engine) # 异步session 区别在于需要指定对应的class_ async_session = sessionmaker(async_engine, class_=AsyncSession) 建立会话 # 我们还是以代码的形式展示:
# 同步 with Session() as session: # 里面是具体的sql操作 pass # 异步 async with Session() as session: # 里面是异步的操作，区别就是从with变成了async with 也就意味着方法必须是async修饰的 pass 以上是关于建立连接，处理会话的一些区别，接着我们讲对应的CRUD操作。"><meta property="og:type" content="article"><meta property="og:url" content="http://example.org/docs/programmer/langs/python/sqlalchemy/"><meta property="article:section" content="docs"><meta property="article:published_time" content="2024-05-16T00:00:00+00:00"><meta property="article:modified_time" content="2024-05-16T00:00:00+00:00"><title>SqlAlchemy - 数据库Orm | Ian's Blog</title>
<link rel=manifest href=/manifest.json><link rel=icon href=/favicon.png type=image/x-icon><link rel=stylesheet href=/book.min.c58292d36b18b675680ab9baea2029204537b839ea72f258746ec0f32ce8d6c8.css integrity="sha256-xYKS02sYtnVoCrm66iApIEU3uDnqcvJYdG7A8yzo1sg=" crossorigin=anonymous><script defer src=/flexsearch.min.js></script><script defer src=/en.search.min.80b0c12c6a3982c23bab5eb1d10c75b4cf8bfbaa1c7e183729648ce8a09207d7.js integrity="sha256-gLDBLGo5gsI7q16x0Qx1tM+L+6ocfhg3KWSM6KCSB9c=" crossorigin=anonymous></script></head><body dir=ltr><input type=checkbox class="hidden toggle" id=menu-control>
<input type=checkbox class="hidden toggle" id=toc-control><main class="container flex"><aside class=book-menu><div class=book-menu-content><nav><h2 class=book-brand><a class="flex align-center" href=/><span>Ian's Blog</span></a></h2><div class=book-search><input type=text id=book-search-input placeholder=Search aria-label=Search maxlength=64 data-hotkeys=s/><div class="book-search-spinner hidden"></div><ul id=book-search-results></ul></div><ul><li class=book-section-flat><a href=/docs/programmer/>程序员笔记</a><ul><li><input type=checkbox id=section-d5f99046a51e5e750b61f2e037945fcc class=toggle>
<label for=section-d5f99046a51e5e750b61f2e037945fcc class="flex justify-between"><a role=button>基础工具和配置</a></label><ul><li><a href=/docs/programmer/basetc/%E6%96%87%E6%9C%AC%E4%B8%89%E5%89%91%E5%AE%A2/>文本三剑客</a></li><li><a href=/docs/programmer/basetc/tmux/>Tmux使用笔记</a></li><li><a href=/docs/programmer/basetc/obsidian%E6%80%9D%E7%BB%B4%E5%AF%BC%E5%9B%BE%E6%8F%92%E4%BB%B6/>Obsidian思维导图插件</a></li><li><a href=/docs/programmer/basetc/for_china/>各个软件换源</a></li><li><a href=/docs/programmer/basetc/tipsofvim/>tip Of vim</a></li><li><a href=/docs/programmer/basetc/editer/>编辑器使用</a></li><li><a href=/docs/programmer/basetc/bash/>Bash</a></li><li><a href=/docs/programmer/basetc/gitbook/>Gitbook</a></li><li><a href=/docs/programmer/basetc/vim/>Vim</a></li><li><a href=/docs/programmer/basetc/%E5%AE%88%E6%8A%A4%E8%BF%9B%E7%A8%8B/>supervisor</a></li></ul></li><li><input type=checkbox id=section-8658298e10b544e890095f646916165a class=toggle>
<label for=section-8658298e10b544e890095f646916165a class="flex justify-between"><a href=/docs/programmer/cloudnative/>云原生</a></label><ul><li><input type=checkbox id=section-31d3b02fd4a132635e483e7e756058ea class=toggle>
<label for=section-31d3b02fd4a132635e483e7e756058ea class="flex justify-between"><a href=/docs/programmer/cloudnative/redis/>中间件</a></label><ul><li><a href=/docs/programmer/cloudnative/redis/python-redis-%E5%AE%A2%E6%88%B7%E7%AB%AF/>Python Redis 客户端</a></li><li><a href=/docs/programmer/cloudnative/redis/bigkey-and-hotkey/>大key、热key问题</a></li><li><a href=/docs/programmer/cloudnative/redis/the-basics-of-redis/>Redis基础</a></li><li><a href=/docs/programmer/cloudnative/redis/advanced-knowledge-of-redis/>Redis进阶</a></li><li><a href=/docs/programmer/cloudnative/redis/%E4%BD%BF%E7%94%A8%E5%91%BD%E4%BB%A4/>Redis常用命令</a></li></ul></li><li><input type=checkbox id=section-62d608ed890b3abc76dae78ccfcab912 class=toggle>
<label for=section-62d608ed890b3abc76dae78ccfcab912 class="flex justify-between"><a role=button>k8s</a></label><ul><li><a href=/docs/programmer/cloudnative/k8s/elk%E5%9C%A8k8s%E4%B8%8A%E7%9A%84%E9%83%A8%E7%BD%B2%E4%BD%BF%E7%94%A8%E7%A4%BA%E4%BE%8B/>elk在k8s上的部署使用示例</a></li><li><a href=/docs/programmer/cloudnative/k8s/k8s-%E9%85%8D%E5%A5%97%E8%AF%B4%E6%98%8E/>k8s 配套说明</a></li><li><a href=/docs/programmer/cloudnative/k8s/k8s-%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/>k8s技术分享</a></li><li><a href=/docs/programmer/cloudnative/k8s/k8s%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%E5%92%8C%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E8%A7%A3%E6%9E%90/>k8s学习-常用命令和配置文件</a></li><li><a href=/docs/programmer/cloudnative/k8s/argo-workflow%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95%E5%92%8C%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF%E5%88%86%E6%9E%90/>Argo Workflow性能测试和使用场景分析</a></li><li><a href=/docs/programmer/cloudnative/k8s/argo-%E4%BD%BF%E7%94%A8%E8%AE%B0%E5%BD%95/>Argo 使用记录</a></li></ul></li><li><input type=checkbox id=section-b828bf3d116bc282da9db25a06bf908e class=toggle>
<label for=section-b828bf3d116bc282da9db25a06bf908e class="flex justify-between"><a role=button>中间件</a></label><ul><li><a href=/docs/programmer/cloudnative/middleware/kafka-%E5%AE%89%E8%A3%85%E5%92%8C%E4%BD%BF%E7%94%A8/>Kafka 安装和使用</a></li></ul></li><li><a href=/docs/programmer/cloudnative/%E5%AE%B9%E5%99%A8/note-of-podman/>Podman</a></li><li><a href=/docs/programmer/cloudnative/nginx%E5%AE%9E%E7%94%A8%E9%85%8D%E7%BD%AE/>Nginx实用配置</a></li><li><a href=/docs/programmer/cloudnative/uwsgi-%E5%A4%84%E7%90%86%E8%AE%B0%E5%BD%95/>uwsgi 处理记录</a></li><li><a href=/docs/programmer/cloudnative/note-of-docker/>Docker</a></li><li><a href=/docs/programmer/cloudnative/%E5%AE%B9%E5%99%A8/note-of-docker/>Docker</a></li><li><a href=/docs/programmer/cloudnative/fastapi/>Django的建站的(｡･･)ﾉﾞ</a></li><li><a href=/docs/programmer/cloudnative/nginx-%E9%AB%98%E5%8F%AF%E7%94%A8/>Nginx高可用</a></li><li><a href=/docs/programmer/cloudnative/notesdjango/>Django的建站的(｡･･)ﾉﾞ</a></li><li><a href=/docs/programmer/cloudnative/sonar-%E4%BB%A3%E7%A0%81%E9%9D%99%E6%80%81%E6%A3%80%E6%9F%A5/>Sonar 代码静态检查</a></li></ul></li><li><input type=checkbox id=section-883e27361d38e16afb68faff3435ac0b class=toggle>
<label for=section-883e27361d38e16afb68faff3435ac0b class="flex justify-between"><a role=button>机器学习</a></label><ul><li><a href=/docs/programmer/ml/stable-diffusion/>AI画图</a></li><li><a href=/docs/programmer/ml/%E7%88%AC%E8%99%AB/>爬虫</a></li><li><a href=/docs/programmer/ml/paddle/>Paddle</a></li><li><a href=/docs/programmer/ml/tensorflow/>Tensorflow</a></li><li><a href=/docs/programmer/ml/opencv/>OpenCV</a></li><li><a href=/docs/programmer/ml/yolo/>Demo Test项目中的一些东西</a></li><li><a href=/docs/programmer/ml/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%B8%B8%E7%94%A8%E5%BA%93%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95/>机器学习库</a></li></ul></li><li><input type=checkbox id=section-0bf4f4329214e20fa67ca3e12c6aad0c class=toggle>
<label for=section-0bf4f4329214e20fa67ca3e12c6aad0c class="flex justify-between"><a role=button>平台</a></label><ul><li><a href=/docs/programmer/platforms/ubuntu/>Ubuntu</a></li><li><a href=/docs/programmer/platforms/%E9%98%BF%E9%87%8C%E4%BA%91%E4%BD%BF%E7%94%A8/>阿里云使用</a></li><li><a href=/docs/programmer/platforms/wps-for-linux/>WPS for Linux</a></li><li><a href=/docs/programmer/platforms/appsflyer/>AppsFlyer-外网移动归因营销分析平台</a></li></ul></li><li><input type=checkbox id=section-bf4e0d6f0b81f7b3ec08ed1fc66b874d class=toggle checked>
<label for=section-bf4e0d6f0b81f7b3ec08ed1fc66b874d class="flex justify-between"><a href=/docs/programmer/langs/>编程语言</a></label><ul><li><input type=checkbox id=section-771df6c720301e69f1715f7fc174ac3d class=toggle checked>
<label for=section-771df6c720301e69f1715f7fc174ac3d class="flex justify-between"><a role=button>Python</a></label><ul><li><a href=/docs/programmer/langs/python/sqlalchemy/ class=active>SqlAlchemy - 数据库Orm</a></li><li><a href=/docs/programmer/langs/python/pypi/>PyPi使用说明</a></li><li><a href=/docs/programmer/langs/python/pytest/>PyTest</a></li><li><a href=/docs/programmer/langs/python/paramiko-%E4%BD%BF%E7%94%A8-sshsftp/>Paramiko 使用 Ssh&amp;sftp</a></li><li><a href=/docs/programmer/langs/python/%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%A4%9A%E8%BF%9B%E7%A8%8B/>Python 多线程多进程</a></li><li><a href=/docs/programmer/langs/python/notespython/>Python 常用库</a></li><li><a href=/docs/programmer/langs/python/notespython/>Python 笔记</a></li><li><a href=/docs/programmer/langs/python/py%E5%B0%8F%E5%B7%A5%E5%85%B7%E5%92%8C%E5%8A%9F%E8%83%BD%E6%80%A7%E6%96%B9%E6%B3%95/>Py小工具和功能性方法</a></li><li><a href=/docs/programmer/langs/python/notespython/>解决问题</a></li></ul></li><li><input type=checkbox id=section-9f8ac8f06e138c7ac13ff61f23b4d497 class=toggle>
<label for=section-9f8ac8f06e138c7ac13ff61f23b4d497 class="flex justify-between"><a role=button>Golang</a></label><ul><li><a href=/docs/programmer/langs/golang/advanced-knowledge-of-golang/>Golang进阶笔记</a></li><li><a href=/docs/programmer/langs/golang/noteofgoexp/>Golang进阶笔记</a></li><li><a href=/docs/programmer/langs/golang/note-of-golang/>Golang笔记</a></li><li><a href=/docs/programmer/langs/golang/noteofgolang/>Golang笔记</a></li></ul></li><li><a href=/docs/programmer/langs/cmake/>CMake 使用Tips</a></li><li><a href=/docs/programmer/langs/tips-of-debugers/>Tips of debuggers</a></li><li><a href=/docs/programmer/langs/tips-of-markdown/>Tips of MarkDown</a></li><li><a href=/docs/programmer/langs/java/notesjava/>愉快的Java(happy to learn the fuck java)</a></li><li><a href=/docs/programmer/langs/note-for-fmtdata/>数据格式笔记</a></li></ul></li><li><input type=checkbox id=section-de7bfad1d124522974cdf8addfbb23f2 class=toggle>
<label for=section-de7bfad1d124522974cdf8addfbb23f2 class="flex justify-between"><a role=button>Net</a></label><ul><li><a href=/docs/programmer/net/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/>网络编程</a></li><li><a href=/docs/programmer/net/nginx%E5%AE%9E%E7%94%A8%E9%85%8D%E7%BD%AE/>Nginx实用配置</a></li><li><a href=/docs/programmer/net/tips-of-grpc/>gRpc使用小记</a></li><li><a href=/docs/programmer/net/epoll%E5%AE%9E%E7%8E%B0/>Epoll实现</a></li><li><a href=/docs/programmer/net/net/>Epoll实现</a></li></ul></li><li><input type=checkbox id=section-4446dd07527142b855f26d7cc8f0e617 class=toggle>
<label for=section-4446dd07527142b855f26d7cc8f0e617 class="flex justify-between"><a href=/docs/programmer/database/>Database</a></label><ul><li><a href=/docs/programmer/database/mongodb/>Mongodb使用记录</a></li><li><a href=/docs/programmer/database/dgraph/>Dgraph使用小记</a></li><li><a href=/docs/programmer/database/note-of-db-data-mongodb/>数据库-MongoDB篇</a></li><li><a href=/docs/programmer/database/note-of-db-data/>数据库-MongoDB篇</a></li><li><a href=/docs/programmer/database/note-of-db-data-mysql/>数据库-MySQL篇</a></li></ul></li><li><input type=checkbox id=section-7e5360c5e7954906b897ed79085884b6 class=toggle>
<label for=section-7e5360c5e7954906b897ed79085884b6 class="flex justify-between"><a href=/docs/programmer/gui/>图形用户界面-GUI</a></label><ul><li><a href=/docs/programmer/gui/pyinstaller-python%E6%89%93%E5%8C%85/>python打包</a></li><li><a href=/docs/programmer/gui/pyinstaller/>python打包</a></li><li><a href=/docs/programmer/gui/qt/>Qt/PySide</a></li><li><a href=/docs/programmer/gui/noteofvn_py/>Vn.Py学习笔记（Python交易平台框架）</a></li><li><a href=/docs/programmer/gui/vn.py%E7%AC%94%E8%AE%B0-%E4%BA%A4%E6%98%93%E5%B9%B3%E5%8F%B0%E5%AE%A2%E6%88%B7%E7%AB%AF/>Vn.Py学习笔记（Python交易平台框架）</a></li><li><a href=/docs/programmer/gui/notespython/>图形化界面 （Python Gui）</a></li><li><a href=/docs/programmer/gui/notespython/>图形化界面 （Python Gui）</a></li></ul></li><li><input type=checkbox id=section-ddcbe632dc99a9fb372422dada8ee641 class=toggle>
<label for=section-ddcbe632dc99a9fb372422dada8ee641 class="flex justify-between"><a role=button>OS操作系统问题处理</a></label><ul><li><a href=/docs/programmer/os/install_some/>安装问题</a></li><li><a href=/docs/programmer/os/android/>安卓</a></li><li><a href=/docs/programmer/os/freebsd/>FreeBSD</a></li><li><a href=/docs/programmer/os/note-of-linux/>Linux 笔记</a></li><li><a href=/docs/programmer/os/npm/>Npm</a></li><li><a href=/docs/programmer/os/git/>Git</a></li><li><a href=/docs/programmer/os/problem-of-windows/>Windows 爬坑记</a></li><li><a href=/docs/programmer/os/tips-of-problems/>解决问题记录笔记</a></li></ul></li><li><input type=checkbox id=section-d325c59fc6513e1b1e05a60b192d4973 class=toggle>
<label for=section-d325c59fc6513e1b1e05a60b192d4973 class="flex justify-between"><a href=/docs/programmer/hardware/>硬件</a></label><ul><li><a href=/docs/programmer/hardware/raspberrypi/>Raspberry Pi</a></li><li><a href=/docs/programmer/hardware/screen/>Screen</a></li></ul></li></ul></li><li class=book-section-flat><span>建模和游戏</span><ul><li><a href=/docs/3dgame/blender/>Blender</a></li><li><a href=/docs/3dgame/noteofue4/>UE4 笔记</a></li></ul></li><li class=book-section-flat><a href=/docs/example/>Hugo特殊Markdown语法说明</a><ul><li><a href=/docs/example/table-of-contents/>Table of Contents</a><ul><li><a href=/docs/example/table-of-contents/with-toc/>With ToC</a></li><li><a href=/docs/example/table-of-contents/without-toc/>Without ToC</a></li></ul></li><li><a href=/docs/example/shortcodes/buttons/>Buttons</a></li><li><a href=/docs/example/shortcodes/columns/>Columns</a></li><li><a href=/docs/example/shortcodes/details/>Details</a></li><li><a href=/docs/example/shortcodes/expand/>Expand</a></li><li><a href=/docs/example/shortcodes/hints/>Hints</a></li><li><a href=/docs/example/shortcodes/tabs/>Tabs</a></li></ul></li></ul><ul><li><a href=/posts/>Blog</a></li></ul></nav><script>(function(){var e=document.querySelector("aside .book-menu-content");addEventListener("beforeunload",function(){localStorage.setItem("menu.scrollTop",e.scrollTop)}),e.scrollTop=localStorage.getItem("menu.scrollTop")})()</script></div></aside><div class=book-page><header class=book-header><div class="flex align-center justify-between"><label for=menu-control><img src=/svg/menu.svg class=book-icon alt=Menu>
</label><strong>SqlAlchemy - 数据库Orm</strong>
<label for=toc-control><img src=/svg/toc.svg class=book-icon alt="Table of Contents"></label></div><aside class="hidden clearfix"><nav id=TableOfContents><ul><li><a href=#异步sqlalchemy>异步SQLAlchemy</a><ul><li><a href=#engine的区别>engine的区别</a></li><li><a href=#session的区别>session的区别</a></li><li><a href=#建立会话>建立会话</a></li><li><a href=#查询>查询</a></li><li><a href=#新增>新增</a></li><li><a href=#编辑>编辑</a></li><li><a href=#删除>删除</a></li></ul></li></ul><ul><li><a href=#逻辑操作符>逻辑操作符</a><ul><li><a href=#1-and-or>1. and or</a></li><li><a href=#2-null>2. null</a></li></ul></li><li><a href=#自适应查询>自适应查询</a></li></ul></nav></aside></header><article class=markdown><h1 id=sqlalchemy异步操作不完全指北---米洛丶---博客园>Sqlalchemy异步操作不完全指北 - 米洛丶 - 博客园
<a class=anchor href=#sqlalchemy%e5%bc%82%e6%ad%a5%e6%93%8d%e4%bd%9c%e4%b8%8d%e5%ae%8c%e5%85%a8%e6%8c%87%e5%8c%97---%e7%b1%b3%e6%b4%9b%e4%b8%b6---%e5%8d%9a%e5%ae%a2%e5%9b%ad>#</a></h1><blockquote><p><a href=https://www.cnblogs.com/we8fans/p/16126577.html>cnblogs.com</a></p></blockquote><h2 id=异步sqlalchemy>异步SQLAlchemy
<a class=anchor href=#%e5%bc%82%e6%ad%a5sqlalchemy>#</a></h2><p>SQLAlchemy作为一款<code>通用</code>的Python Orm工具，在最近的版本也支持了异步操作。但网上很多资料都不是很齐全，API也不是很好查询的情况下，我便有了整理一份基础文档的想法。文章主要会以CRUD为入口，解决大家最基本的需求。</p><h3 id=engine的区别>engine的区别
<a class=anchor href=#engine%e7%9a%84%e5%8c%ba%e5%88%ab>#</a></h3><p>在普通的SQLAlchemy中，建立engine对象，我们会采用下面的方式:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> sqlalchemy <span style=color:#f92672>import</span> create_engine
</span></span><span style=display:flex><span>engine <span style=color:#f92672>=</span> create_engine(SQLALCHEMY_DATABASE_URI, pool_recycle<span style=color:#f92672>=</span><span style=color:#ae81ff>1500</span>)
</span></span></code></pre></div><p>而异步的方式如下:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> sqlalchemy.ext.asyncio <span style=color:#f92672>import</span> create_async_engine
</span></span><span style=display:flex><span>async_engine <span style=color:#f92672>=</span> create_async_engine(ASYNC_SQLALCHEMY_URI, pool_recycle<span style=color:#f92672>=</span><span style=color:#ae81ff>1500</span>)
</span></span></code></pre></div><h3 id=session的区别>session的区别
<a class=anchor href=#session%e7%9a%84%e5%8c%ba%e5%88%ab>#</a></h3><p>我们一般用sessionmaker来建立session，不过异步的有点区别:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> sqlalchemy.ext.asyncio <span style=color:#f92672>import</span> AsyncSession
</span></span><span style=display:flex><span><span style=color:#f92672>from</span> sqlalchemy.orm <span style=color:#f92672>import</span> sessionmaker
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#75715e># 同步session</span>
</span></span><span style=display:flex><span>Session <span style=color:#f92672>=</span> sessionmaker(engine)
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#75715e># 异步session 区别在于需要指定对应的class_</span>
</span></span><span style=display:flex><span>async_session <span style=color:#f92672>=</span> sessionmaker(async_engine, class_<span style=color:#f92672>=</span>AsyncSession)
</span></span></code></pre></div><h3 id=建立会话>建立会话
<a class=anchor href=#%e5%bb%ba%e7%ab%8b%e4%bc%9a%e8%af%9d>#</a></h3><p>我们还是以代码的形式展示:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#75715e># 同步</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>with</span> Session() <span style=color:#66d9ef>as</span> session:
</span></span><span style=display:flex><span>  <span style=color:#75715e># 里面是具体的sql操作</span>
</span></span><span style=display:flex><span>  <span style=color:#66d9ef>pass</span>
</span></span><span style=display:flex><span>  
</span></span><span style=display:flex><span><span style=color:#75715e># 异步</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>async</span> <span style=color:#66d9ef>with</span> Session() <span style=color:#66d9ef>as</span> session:
</span></span><span style=display:flex><span>    <span style=color:#75715e># 里面是异步的操作，区别就是从with变成了async with 也就意味着方法必须是async修饰的</span>
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>pass</span>
</span></span></code></pre></div><hr><p>以上是关于建立连接，处理会话的一些区别，接着我们讲对应的CRUD操作。</p><h3 id=查询>查询
<a class=anchor href=#%e6%9f%a5%e8%af%a2>#</a></h3><p>这里依旧会给出新老版本的对比:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#75715e># 注意Session为同步Session，为了区分，异步session为async_session</span>
</span></span><span style=display:flex><span><span style=color:#75715e># model则为具体的Model类</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#75715e># 异步查询方式</span>
</span></span><span style=display:flex><span><span style=color:#f92672>from</span> sqlalchemy <span style=color:#f92672>import</span> select
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>async</span> <span style=color:#66d9ef>def</span> <span style=color:#a6e22e>query</span>():
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>async</span> <span style=color:#66d9ef>with</span> async_session() <span style=color:#66d9ef>as</span> session:
</span></span><span style=display:flex><span>        sql <span style=color:#f92672>=</span> select(model)<span style=color:#f92672>.</span>where(model<span style=color:#f92672>.</span>id <span style=color:#f92672>==</span> <span style=color:#ae81ff>1</span>)
</span></span><span style=display:flex><span>        print(sql) <span style=color:#75715e># 这里可以打印出sql</span>
</span></span><span style=display:flex><span>        result <span style=color:#f92672>=</span> <span style=color:#66d9ef>await</span> session<span style=color:#f92672>.</span>execute(sql)
</span></span><span style=display:flex><span>        <span style=color:#75715e># 第一条数据</span>
</span></span><span style=display:flex><span>        data <span style=color:#f92672>=</span> result<span style=color:#f92672>.</span>scalars()<span style=color:#f92672>.</span>first()
</span></span><span style=display:flex><span>        <span style=color:#75715e># 所有数据</span>
</span></span><span style=display:flex><span>        <span style=color:#75715e># data = result.scalars().all()</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#75715e># 同步查询方式一</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>query</span>():
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>with</span> Session() <span style=color:#66d9ef>as</span> session:
</span></span><span style=display:flex><span>        <span style=color:#75715e># 查询id=1的第一条数据 result对应的就是model的实例 如果没有则是None</span>
</span></span><span style=display:flex><span>        result <span style=color:#f92672>=</span> session<span style=color:#f92672>.</span>query(model)<span style=color:#f92672>.</span>filter_by(id<span style=color:#f92672>=</span><span style=color:#ae81ff>1</span>)<span style=color:#f92672>.</span>first()
</span></span><span style=display:flex><span>        <span style=color:#75715e># 查询所有数据 result对应的数据为List[model]，即model数组</span>
</span></span><span style=display:flex><span>        <span style=color:#75715e># result = session.query(model).filter_by(name=&#34;zhangsan&#34;).all()</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#75715e># 同步查询方式二</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>query</span>():
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>with</span> Session() <span style=color:#66d9ef>as</span> session:
</span></span><span style=display:flex><span>        <span style=color:#75715e># 查询id=1的第一条数据 result对应的就是model的实例 如果没有则是None</span>
</span></span><span style=display:flex><span>        result <span style=color:#f92672>=</span> session<span style=color:#f92672>.</span>query(model)<span style=color:#f92672>.</span>filter(model<span style=color:#f92672>.</span>id <span style=color:#f92672>==</span> <span style=color:#ae81ff>1</span>)<span style=color:#f92672>.</span>first()
</span></span><span style=display:flex><span>        <span style=color:#75715e># 查询所有数据 result对应的数据为List[model]，即model数组</span>
</span></span><span style=display:flex><span>        <span style=color:#75715e># result = session.query(model).filter(model.name == &#34;zhangsan&#34;).all()</span>
</span></span></code></pre></div><h3 id=新增>新增
<a class=anchor href=#%e6%96%b0%e5%a2%9e>#</a></h3><p>这里开始就只讲异步的操作了。</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>data <span style=color:#f92672>=</span> DataModel(name<span style=color:#f92672>=</span><span style=color:#e6db74>&#39;&#39;</span>, phone<span style=color:#f92672>=</span><span style=color:#e6db74>&#39;&#39;</span>)
</span></span><span style=display:flex><span><span style=color:#66d9ef>async</span> <span style=color:#66d9ef>def</span> <span style=color:#a6e22e>insert</span>(data):
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>async</span> <span style=color:#66d9ef>with</span> async_session() <span style=color:#66d9ef>as</span> session:
</span></span><span style=display:flex><span>        <span style=color:#66d9ef>async</span> <span style=color:#66d9ef>with</span> session<span style=color:#f92672>.</span>begin():
</span></span><span style=display:flex><span>            session<span style=color:#f92672>.</span>add(data)
</span></span><span style=display:flex><span>            <span style=color:#75715e># 刷新自带的主键</span>
</span></span><span style=display:flex><span>            <span style=color:#66d9ef>await</span> session<span style=color:#f92672>.</span>flush()
</span></span><span style=display:flex><span>            <span style=color:#75715e># 释放这个data数据</span>
</span></span><span style=display:flex><span>            session<span style=color:#f92672>.</span>expunge(data)
</span></span><span style=display:flex><span>            <span style=color:#66d9ef>return</span> data
</span></span></code></pre></div><p>先说一下session.begin，这个你可以理解为一个事务操作，当采用session的begin方法后，你可以发现我们不需要调用commit方法也能把修改存入数据库。</p><p>expunge方法，是用例释放这个实例，SQLAlchemy有个特点，当你的session会话结束以后，它会销毁你插入的这种临时数据，你再想访问这个data就访问不了了。所以我们可以释放这个数据。（expunge的作用）</p><h3 id=编辑>编辑
<a class=anchor href=#%e7%bc%96%e8%be%91>#</a></h3><p>一般编辑有2种方式:</p><ul><li>查询出对应的数据，在数据上修改</li><li>根据key-value的形式，修改对应数据的字段</li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> sqlalchemy <span style=color:#f92672>import</span> select, update
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#75715e># 方式一</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>async</span> <span style=color:#66d9ef>def</span> <span style=color:#a6e22e>update_record</span>(model):
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>async</span> <span style=color:#66d9ef>with</span> async_session() <span style=color:#66d9ef>as</span> session:
</span></span><span style=display:flex><span>        <span style=color:#66d9ef>async</span> <span style=color:#66d9ef>with</span> session<span style=color:#f92672>.</span>begin():
</span></span><span style=display:flex><span>            result <span style=color:#f92672>=</span> <span style=color:#66d9ef>await</span> session<span style=color:#f92672>.</span>execute(select(model)<span style=color:#f92672>.</span>where(id<span style=color:#f92672>=</span><span style=color:#ae81ff>1</span>))
</span></span><span style=display:flex><span>            now <span style=color:#f92672>=</span> result<span style=color:#f92672>.</span>scalars()<span style=color:#f92672>.</span>first()
</span></span><span style=display:flex><span>            <span style=color:#66d9ef>if</span> now <span style=color:#f92672>is</span> <span style=color:#66d9ef>None</span>:
</span></span><span style=display:flex><span>                <span style=color:#66d9ef>raise</span> <span style=color:#a6e22e>Exception</span>(<span style=color:#e6db74>&#34;记录不存在&#34;</span>)
</span></span><span style=display:flex><span>            now<span style=color:#f92672>.</span>name <span style=color:#f92672>=</span> <span style=color:#e6db74>&#34;李四&#34;</span>
</span></span><span style=display:flex><span>            now<span style=color:#f92672>.</span>age <span style=color:#f92672>=</span> <span style=color:#ae81ff>23</span>
</span></span><span style=display:flex><span>            <span style=color:#75715e># 这里测试过，如果去掉flush会导致数据不更新</span>
</span></span><span style=display:flex><span>            <span style=color:#66d9ef>await</span> session<span style=color:#f92672>.</span>flush()
</span></span><span style=display:flex><span>            session<span style=color:#f92672>.</span>expunge(now)
</span></span><span style=display:flex><span>            <span style=color:#66d9ef>return</span> now
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#75715e># 方式二</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>async</span> <span style=color:#66d9ef>def</span> <span style=color:#a6e22e>update_by_map</span>():
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>async</span> <span style=color:#66d9ef>with</span> async_session() <span style=color:#66d9ef>as</span> session:
</span></span><span style=display:flex><span>        <span style=color:#66d9ef>async</span> <span style=color:#66d9ef>with</span> session<span style=color:#f92672>.</span>begin():
</span></span><span style=display:flex><span>            <span style=color:#75715e># 更新id为1的数据，并把name改为李四 age改为23</span>
</span></span><span style=display:flex><span>            sql <span style=color:#f92672>=</span> update(model)<span style=color:#f92672>.</span>where(model<span style=color:#f92672>.</span>id <span style=color:#f92672>==</span> <span style=color:#ae81ff>1</span>)<span style=color:#f92672>.</span>values(name<span style=color:#f92672>=</span><span style=color:#e6db74>&#34;李四&#34;</span>, age<span style=color:#f92672>=</span><span style=color:#ae81ff>23</span>)
</span></span><span style=display:flex><span>            <span style=color:#66d9ef>await</span> session<span style=color:#f92672>.</span>execute(sql)
</span></span></code></pre></div><h3 id=删除>删除
<a class=anchor href=#%e5%88%a0%e9%99%a4>#</a></h3><p>删除的话，软删除大家都是update，所以不需要多说，物理删除的话，也有两种方式:</p><ul><li>查到以后删除之</li><li>直接根据条件删除（这种我没有仔细研究，我选的是第一种方式，容错率高点）</li></ul><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>async</span> <span style=color:#66d9ef>def</span> <span style=color:#a6e22e>delete_by_id</span>():
</span></span><span style=display:flex><span>    <span style=color:#66d9ef>async</span> <span style=color:#66d9ef>with</span> async_session() <span style=color:#66d9ef>as</span> session:
</span></span><span style=display:flex><span>        <span style=color:#66d9ef>async</span> <span style=color:#66d9ef>with</span> session<span style=color:#f92672>.</span>begin():
</span></span><span style=display:flex><span>            result <span style=color:#f92672>=</span> <span style=color:#66d9ef>await</span> session<span style=color:#f92672>.</span>execute(select(model)<span style=color:#f92672>.</span>where(model<span style=color:#f92672>.</span>id <span style=color:#f92672>==</span> <span style=color:#ae81ff>2</span>))
</span></span><span style=display:flex><span>            original <span style=color:#f92672>=</span> result<span style=color:#f92672>.</span>scalars()<span style=color:#f92672>.</span>first()
</span></span><span style=display:flex><span>            <span style=color:#66d9ef>if</span> original <span style=color:#f92672>is</span> <span style=color:#66d9ef>None</span>:
</span></span><span style=display:flex><span>                <span style=color:#66d9ef>raise</span> <span style=color:#a6e22e>Exception</span>(<span style=color:#e6db74>&#34;记录不存在&#34;</span>)
</span></span><span style=display:flex><span>            <span style=color:#75715e># 如果是多条</span>
</span></span><span style=display:flex><span>            <span style=color:#75715e># session.delete(original)</span>
</span></span><span style=display:flex><span>            <span style=color:#75715e># for item in result:</span>
</span></span><span style=display:flex><span>            <span style=color:#75715e>#     session.delete(item)</span>
</span></span></code></pre></div><h1 id=压缩>压缩
<a class=anchor href=#%e5%8e%8b%e7%bc%a9>#</a></h1><blockquote><p>并不支持 mysql <code>--compress</code> 连接参数，以下是个伪实现</p></blockquote><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> sqlalchemy.orm
</span></span><span style=display:flex><span><span style=color:#f92672>import</span> validates
</span></span><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>MyClass</span>(Base):
</span></span><span style=display:flex><span>	<span style=color:#75715e># ... </span>
</span></span><span style=display:flex><span>	data <span style=color:#f92672>=</span> Column(BLOB)
</span></span><span style=display:flex><span>	<span style=color:#a6e22e>@validates</span>(<span style=color:#e6db74>&#34;data&#34;</span>)
</span></span><span style=display:flex><span>	<span style=color:#66d9ef>def</span> <span style=color:#a6e22e>_set_data</span>(self, key, value):
</span></span><span style=display:flex><span>		<span style=color:#66d9ef>return</span> func<span style=color:#f92672>.</span>compress(value)
</span></span></code></pre></div><h1 id=查询-1>查询
<a class=anchor href=#%e6%9f%a5%e8%af%a2-1>#</a></h1><h2 id=逻辑操作符>逻辑操作符
<a class=anchor href=#%e9%80%bb%e8%be%91%e6%93%8d%e4%bd%9c%e7%ac%a6>#</a></h2><h3 id=1-and-or>1. and or
<a class=anchor href=#1-and-or>#</a></h3><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> sqlalchemy <span style=color:#f92672>import</span> and_, or_
</span></span><span style=display:flex><span>print(
</span></span><span style=display:flex><span>    select(Address<span style=color:#f92672>.</span>email_address)<span style=color:#f92672>.</span>where(
</span></span><span style=display:flex><span>        and_(
</span></span><span style=display:flex><span>            or_(User<span style=color:#f92672>.</span>name <span style=color:#f92672>==</span> <span style=color:#e6db74>&#34;squidward&#34;</span>, User<span style=color:#f92672>.</span>name <span style=color:#f92672>==</span> <span style=color:#e6db74>&#34;sandy&#34;</span>),
</span></span><span style=display:flex><span>            Address<span style=color:#f92672>.</span>user_id <span style=color:#f92672>==</span> User<span style=color:#f92672>.</span>id,
</span></span><span style=display:flex><span>        )
</span></span><span style=display:flex><span>    )
</span></span><span style=display:flex><span>)
</span></span></code></pre></div><h3 id=2-null>2. null
<a class=anchor href=#2-null>#</a></h3><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>sql <span style=color:#f92672>=</span> select(DeviceData)<span style=color:#f92672>.</span>where(DeviceData<span style=color:#f92672>.</span>device_json_new<span style=color:#f92672>.</span>is_not(<span style=color:#66d9ef>None</span>))
</span></span></code></pre></div><h2 id=自适应查询>自适应查询
<a class=anchor href=#%e8%87%aa%e9%80%82%e5%ba%94%e6%9f%a5%e8%af%a2>#</a></h2><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>async</span> <span style=color:#66d9ef>with</span> async_session_install() <span style=color:#66d9ef>as</span> session:
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#75715e># 使用 DeviceData 模型直接构建查询</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>sql <span style=color:#f92672>=</span> select(DeviceData)<span style=color:#f92672>.</span>where(DeviceData<span style=color:#f92672>.</span>device_json_new<span style=color:#f92672>.</span>is_not(<span style=color:#66d9ef>None</span>))
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>sql_max_min <span style=color:#f92672>=</span> select(
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>func<span style=color:#f92672>.</span>max(DeviceData<span style=color:#f92672>.</span>id)<span style=color:#f92672>.</span>label(<span style=color:#e6db74>&#34;max_id&#34;</span>),
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>func<span style=color:#f92672>.</span>min(DeviceData<span style=color:#f92672>.</span>id)<span style=color:#f92672>.</span>label(<span style=color:#e6db74>&#34;min_id&#34;</span>)
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>)<span style=color:#f92672>.</span>where(DeviceData<span style=color:#f92672>.</span>device_json_new<span style=color:#f92672>.</span>is_not(<span style=color:#66d9ef>None</span>), DeviceData<span style=color:#f92672>.</span>brand_name <span style=color:#f92672>==</span> )
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>for</span> key, value <span style=color:#f92672>in</span> filters<span style=color:#f92672>.</span>items():
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#f92672>not</span> hasattr(DeviceData, key):
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>continue</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>sql <span style=color:#f92672>=</span> sql<span style=color:#f92672>.</span>where(getattr(DeviceData, key) <span style=color:#f92672>==</span> value)
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> limit <span style=color:#f92672>!=</span> <span style=color:#ae81ff>0</span>:
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>sql <span style=color:#f92672>=</span> sql<span style=color:#f92672>.</span>limit(limit)
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>if</span> offset:
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>sql <span style=color:#f92672>=</span> sql<span style=color:#f92672>.</span>offset(offset)
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>logger<span style=color:#f92672>.</span>debug(<span style=color:#e6db74>f</span><span style=color:#e6db74>&#34;fetch sql is: </span><span style=color:#e6db74>{</span>sql<span style=color:#e6db74>}</span><span style=color:#e6db74>&#34;</span>)
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>exec <span style=color:#f92672>=</span> <span style=color:#66d9ef>await</span> session<span style=color:#f92672>.</span>execute(sql)
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>results <span style=color:#f92672>=</span> exec<span style=color:#f92672>.</span>scalars()<span style=color:#f92672>.</span>all()
</span></span></code></pre></div></article><footer class=book-footer><div class="flex flex-wrap justify-between"></div><script>(function(){function e(e){const t=window.getSelection(),n=document.createRange();n.selectNodeContents(e),t.removeAllRanges(),t.addRange(n)}document.querySelectorAll("pre code").forEach(t=>{t.addEventListener("click",function(){if(window.getSelection().toString())return;e(t.parentElement),navigator.clipboard&&navigator.clipboard.writeText(t.parentElement.textContent)})})})()</script></footer><div class=book-comments></div><label for=menu-control class="hidden book-menu-overlay"></label></div><aside class=book-toc><div class=book-toc-content><nav id=TableOfContents><ul><li><a href=#异步sqlalchemy>异步SQLAlchemy</a><ul><li><a href=#engine的区别>engine的区别</a></li><li><a href=#session的区别>session的区别</a></li><li><a href=#建立会话>建立会话</a></li><li><a href=#查询>查询</a></li><li><a href=#新增>新增</a></li><li><a href=#编辑>编辑</a></li><li><a href=#删除>删除</a></li></ul></li></ul><ul><li><a href=#逻辑操作符>逻辑操作符</a><ul><li><a href=#1-and-or>1. and or</a></li><li><a href=#2-null>2. null</a></li></ul></li><li><a href=#自适应查询>自适应查询</a></li></ul></nav></div></aside></main></body></html>